home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 April: Mac OS SDK / Dev.CD Apr 97 SDK1.toast / Development Kits (Disc 1) / Apple Remote Access API / ARA Security API 1.0 / Sample Protocol Module / SampleUserConfigModule.c < prev   
Encoding:
Text File  |  1993-11-04  |  17.2 KB  |  571 lines  |  [TEXT/MPS ]

  1. //234567890123456789012345678901234567890123456789012345678901234567890123456789
  2. //===========================================================================
  3. //    File:    SampleUserConfigModule.c
  4. //
  5. //    This is the user configuration code resource of the sample add-on security
  6. //    module for Apple Remote Access.  This code resource is responsible
  7. //    for putting up a dialog box on the server to configure this security
  8. //    for a user.
  9. //
  10. //    It displays a dialog box that the admin can put an extra password into.
  11. //    During authentication the user is required to enter this additional
  12. //    password.
  13. //
  14. //    Copyright © 1992, 1993 Apple Computer Inc.
  15. //    All rights reserved
  16. //
  17. //    Author:  Farzad Sarabi
  18. //
  19. //    Modification history:
  20. //
  21. //    5/3/1993    Farzad        Updated the code for changes in the Security
  22. //                            Manager such as setting up of the A5 world.
  23. //    12/14/1992    Farzad        Created sample source from the shell file
  24. //    10/6/1992    Farzad        Created
  25. //===========================================================================
  26.  
  27.  
  28. #include    <Types.h>
  29. #include    <Memory.h>
  30. #include    <Resources.h>
  31. #include    <Dialogs.h>
  32.  
  33. #include    "SecurityInterface.h"    // has the interface for ARA services
  34.  
  35.  
  36.  
  37.  
  38. //===========================================================================
  39. //    Macros
  40. //===========================================================================
  41.  
  42. #define kUserConfigDialogID        129
  43. #define kOKButtonID                1
  44. #define kCancelButtonID            2
  45. #define kPasswordBoxID            3
  46. #define kDialogTitleID            4
  47.  
  48.  
  49.  
  50. //===========================================================================
  51. //    Types
  52. //===========================================================================
  53.  
  54. // the following enumeration defines the states that our state machine
  55. // will use.  They are used as either the CompletionParam field of the
  56. // the completion routine, or as the LongParam for a kSecurityTickleAction.
  57. // Using them in this way we can step through the state machine.
  58.  
  59. typedef enum
  60. {
  61.     kStateMiscCompletion,            // used for all the other completions
  62.                                     // we don't care about
  63.     kStateGotPassword,                // got the existing password
  64.     kStatePutUpDialog,                // display the dialog, this must be
  65.                                     // done during a tickle action
  66.     kStateStoredPassword,            // wrote the new password out
  67.     kStateFinish                    // used to indicate operation is
  68.                                     // complete, and we should call
  69.                                     // ARACompleteOperation
  70.  
  71. } TUserConfigStates;
  72.  
  73.  
  74. // An A5 world is setup for this module, so we can have global data such
  75. // as the following
  76. static struct
  77. {
  78.         char            fold_password[ kSecurityMaxConfigData ];
  79.         char            fuser_name[ kSecurityUserInfoLength ];
  80.         DialogPtr        fconfig_dialog;        // configuration dialog
  81.  
  82. } MyData;                            // statically allocated in our
  83.                                     // A5 world
  84.  
  85.  
  86.  
  87.  
  88. // function prototypes
  89. static long        DoMyStartup( MyReference, LongParam );
  90. static long        DoMyShutdown( MyReference, LongParam );
  91. static long        DoMyBegin( MyReference, LongParam );
  92. static long        DoMyEnd( MyReference, LongParam );
  93. static long        DoMyDataHandler( MyReference, LongParam );
  94. static long        DoMyAbortHandler( MyReference, LongParam );
  95. static long        DoMyTickleHandler( MyReference, LongParam );
  96.  
  97. pascal void        MyCompletionProc( SecurityReference        MyReference,
  98.                                   int                    ResultCode,
  99.                                   void                    * DataPtr,
  100.                                   int                    DataSize,
  101.                                   long                    CompletionParam );
  102.  
  103.  
  104.  
  105.  
  106. // this function is the entry point into this code resource, and it should
  107. // be the first function definition in this module.  Also, during link
  108. // time this module should be the first object file listed.
  109.  
  110. pascal long        MySecurityProcEntry( SecurityActions        Action,
  111.                                      SecurityReference        MyReference,
  112.                                      long                    LongParam )
  113. //===========================================================================
  114. //    Description:    this is the entry point for the ??? security operation.
  115. //                    It is called by AppleTalk Remote Access to have this
  116. //                    security module perform the given operation.  It
  117. //                    dispatches to a variety of routines based on the
  118. //                    requested action.
  119. //
  120. //    Parameters:        Action                the action to be performed
  121. //                    MyReference            this is a unique value representing
  122. //                                        this instance of this code module.
  123. //                    DataPtr                the data for this action
  124. //                    DataSize            the size of data
  125. //
  126. //    Return Value:    long                result code, nonzero indicates an
  127. //                                        error.  Its value is one of the
  128. //                                        SecurityResultCodes.
  129. //
  130. //    Creation Date:
  131. //
  132. //    Modifications:
  133. //
  134. //===========================================================================
  135. {
  136.     switch ( Action )    {
  137.  
  138.       case    kSecurityStartup:
  139.         return DoMyStartup( MyReference, LongParam );
  140.  
  141.  
  142.       case    kSecurityShutdown:
  143.           return DoMyShutdown( MyReference, LongParam );
  144.  
  145.  
  146.       case    kSecurityBegin:
  147.           return DoMyBegin( MyReference, LongParam );
  148.  
  149.  
  150.       case    kSecurityEnd:
  151.           return DoMyEnd( MyReference, LongParam );
  152.  
  153.  
  154.       case    kSecurityDataAvailable:
  155.         return DoMyDataHandler( MyReference, LongParam );
  156.  
  157.  
  158.       case    kSecurityAbort:
  159.         return DoMyAbortHandler( MyReference, LongParam );
  160.  
  161.  
  162.       case    kSecurityTickleAction:
  163.           return DoMyTickleHandler( MyReference, LongParam );
  164.  
  165.     }
  166.  
  167.     return ( kSecurityUnsupportedAction );
  168. }
  169.  
  170.  
  171.  
  172.  
  173. static long        DoMyStartup( MyReference, LongParam )
  174. //===========================================================================
  175. //    Description:    this routine setsup our environment.  It allocates the
  176. //                    memory we need and readies this resource for operating.
  177. //
  178. //    Parameters:        MyReference        My unique reference
  179. //                    LongParam        additional information
  180. //
  181. //    Return Value:    long            result code, nonzero indicates error
  182. //
  183. //    Creation Date:
  184. //
  185. //    Modifications:
  186. //
  187. //===========================================================================
  188. {
  189. #pragma unused(LongParam,MyReference)
  190.  
  191.     // we don't need to do anything during the Startup action.
  192.     // normally we could allocate memory and other types of initialization
  193.     // prior to actually doing any work
  194.  
  195.     return ( kSecurityNoErr );
  196. }
  197.  
  198.  
  199.  
  200. static long        DoMyShutdown( MyReference, LongParam )
  201. //===========================================================================
  202. //    Description:    this routine handles the kSecurityShutdown action.  It
  203. //                    cleans up any allocated memory.
  204. //
  205. //    Parameters:        MyReference        My unique reference
  206. //                    LongParam        additional information
  207. //
  208. //    Return Value:    long            result code, nonzero indicates error
  209. //
  210. //    Creation Date:
  211. //
  212. //    Modifications:
  213. //
  214. //===========================================================================
  215. {
  216. #pragma unused(MyReference,LongParam)
  217.  
  218.     // We don't need to do anything here for the Shutdown action.
  219.     // normally we would be releasing any resources that are allocated by
  220.     // this module here.
  221.     // this is the very last messages that is sent to the module
  222.  
  223.     return ( kSecurityNoErr );
  224. }
  225.  
  226.  
  227.  
  228. static long        DoMyBegin( MyReference, LongParam )
  229. //===========================================================================
  230. //    Description:    this routine is where we actually start doing work.  When
  231. //                    we are called, we have already setup our memory area.
  232. //                    We first request our old password, and we can then
  233. //                    display our dialog box, and get the new password.
  234. //
  235. //    Parameters:        MyReference        My unique reference
  236. //                    LongParam        additional information
  237. //
  238. //    Return Value:    long            result code, nonzero indicates error
  239. //
  240. //    Creation Date:
  241. //
  242. //    Modifications:
  243. //
  244. //===========================================================================
  245. {
  246.  
  247. #pragma unused(LongParam)                    // so we don't get compiler warnings
  248.  
  249.     // We need to start the processing here when we get the Begin action.
  250.     // We must get the user's name and existing password (i.e. secondary
  251.     // password).
  252.     // 
  253.     // notice we use the CompletionParam as the next state we will transition
  254.     // to when this call completes.  The states are defined above in
  255.     // TUserConfigStates
  256.  
  257.     if (( ARAGetUserInfo( MyReference,
  258.                           MyData.fuser_name,    // store it here
  259.                           sizeof( MyData.fuser_name ),
  260.                           MyCompletionProc,
  261.                           kStateMiscCompletion ) != ARANoErr ) ||
  262.                                                   // ignore the completion for this
  263.                                                 // call and get the password also
  264.         ( ARAReadLockSecurityData( MyReference,
  265.                                    MyData.fold_password,
  266.                                    sizeof( MyData.fold_password ),
  267.                                    MyCompletionProc,
  268.                                    kStateGotPassword ) != ARANoErr ))
  269.     {
  270.         // something failed in the ARA services, don't even continue
  271.         ARACompleteOperation( MyReference );
  272.         return ( kSecurityGenericErr );
  273.     }
  274.     // we are done here, when this call completes
  275.     return ( kSecurityNoErr );
  276. }
  277.  
  278.  
  279.  
  280. static long        DoMyEnd( MyReference, LongParam )
  281. //===========================================================================
  282. //    Description:    this routine handles the kSecurityEnd action.  The action
  283. //                    is sent to signal the end of the operation the code
  284. //                    resource was created to do.
  285. //
  286. //    Parameters:        MyReference        My unique reference
  287. //                    LongParam        additional information
  288. //
  289. //    Return Value:    long            result code, nonzero indicates error
  290. //
  291. //    Creation Date:
  292. //
  293. //    Modifications:
  294. //
  295. //===========================================================================
  296. {
  297. #pragma unused(MyReference,LongParam)
  298.  
  299.     // this action is sent as a response to one of our requests (e.g.
  300.     // ARACompleteOperation) for ending the process
  301.  
  302.     // We would normally use this as an indicator that the operation that
  303.     // the module is performing is ended as per our request.  We could do
  304.     // some cleanup here.  We should then wait for the ShutDown action as
  305.     // an indication that our module will be unloaded.
  306.  
  307.     return ( kSecurityNoErr );
  308. }
  309.  
  310.  
  311.  
  312. static long        DoMyDataHandler( MyReference, LongParam )
  313. //===========================================================================
  314. //    Description:    this routine handles the kSecurityDataAvailable action.
  315. //                    The action is sent when data has arrived for the code
  316. //                    resource.
  317. //
  318. //    Parameters:        MyReference        My unique reference
  319. //                    LongParam        additional information
  320. //
  321. //    Return Value:    long            result code, nonzero indicates error
  322. //
  323. //    Creation Date:
  324. //
  325. //    Modifications:
  326. //
  327. //===========================================================================
  328. {
  329. #pragma unused(MyReference,LongParam)
  330.  
  331.     // Currently DataAvailable action is not being used.  It may in the future
  332.     // be put to some use.  One possible use might be for cases when you have
  333.     // a modeless dialog box.  We could send you the events through the use
  334.     // of this action.
  335.  
  336.     // This action might also be used when we get data during
  337.     // the authentication process, and you don't have a read pending.
  338.  
  339.     // Again, it is not used now but may be used in the future!
  340.  
  341.     return ( kSecurityNoErr );
  342. }
  343.  
  344.  
  345.  
  346. static long        DoMyAbortHandler( MyReference, LongParam )
  347. //===========================================================================
  348. //    Description:    this routine handles the kSecurityAbort action.  The
  349. //                    abort action is sent when the code resources operation
  350. //                    needs to be terminated abnormally.
  351. //
  352. //    Parameters:        MyReference        My unique reference
  353. //                    LongParam        additional information
  354. //
  355. //    Return Value:    long            result code, nonzero indicates error
  356. //
  357. //    Creation Date:
  358. //
  359. //    Modifications:
  360. //
  361. //===========================================================================
  362. {
  363. #pragma unused(MyReference,LongParam)
  364.  
  365.     // We are being aborted.  You need to abort what you are doing.  
  366.     // ARAServices will not be available after this (at least the read and
  367.     // writes will not be available, but you shouldn't expect any of the
  368.     // ARA services to be available).  The kSecurityAbort action is sent
  369.     // because of some type of exception.
  370.  
  371.     return ( kSecurityNoErr );
  372. }
  373.  
  374.  
  375.  
  376. static long        DoMyTickleHandler( MyReference, LongParam )
  377. //===========================================================================
  378. //    Description:    this routine is called periodically so we can perform
  379. //                    periodic tasks.  It is also called when we call
  380. //                    ARATickleMe.  It is called at non-interrupt time, so
  381. //                    we can perform memory management, etc.  We use it to
  382. //                    do the operations that need to be done at this time,
  383. //                    e.g. the dialog box is displayed in this routine.  We
  384. //                    use the LongParam (which is 0 if ARA calls us) to
  385. //                    show the state which we need to handle.
  386. //                    
  387. //
  388. //    Parameters:        MyReference        My unique reference
  389. //                    LongParam        When ARA calls this value will be 0,
  390. //                                    otherwise it is the value passed to
  391. //                                    the ARATickleMe routine.  We use this
  392. //                                    to show the state we need to handle.
  393. //
  394. //    Return Value:    long            result code, nonzero indicates error
  395. //
  396. //    Creation Date:
  397. //
  398. //    Modifications:
  399. //
  400. //===========================================================================
  401. {
  402. #pragma unused(LongParam)
  403.  
  404.  
  405.     // since we only care about one state here, we will use an if statement
  406.     // otherwise we could use a switch
  407.  
  408.     if ( LongParam == kStatePutUpDialog )
  409.     {
  410.         short                item_hit;
  411.         Handle                item_handle;
  412.         short                item_type;
  413.         Rect                item_box;
  414.  
  415.         // our resource file is on top of the resource file chain
  416.         // get our configuration dialog box
  417.         MyData.fconfig_dialog = GetNewDialog( kUserConfigDialogID,
  418.                                               nil,
  419.                                               (WindowPtr) -1 );
  420.         if ( MyData.fconfig_dialog == nil )
  421.         {
  422.             ARALogMessage( MyReference,
  423.                            "\pCouldn't load user configuration dialog",
  424.                            MyCompletionProc,
  425.                            kStateFinish );
  426.             return ( kSecurityGenericErr );
  427.         }
  428.         // In the following there should be more error checking on the
  429.         // returned items from the Mac Toolbox, but to keep the code
  430.         // clearer, I don't do all error checking some.
  431.         // now set the dialog title and old password
  432.         GetDItem( MyData.fconfig_dialog,
  433.                   kDialogTitleID,
  434.                   & item_type,
  435.                   & item_handle,
  436.                   & item_box );
  437.         SetIText( item_handle, MyData.fuser_name );
  438.  
  439.         GetDItem( MyData.fconfig_dialog,
  440.                   kPasswordBoxID,
  441.                   & item_type,
  442.                   & item_handle,
  443.                   & item_box );
  444.         SetIText( item_handle, MyData.fold_password );
  445.  
  446.         do
  447.         {
  448.             ModalDialog( nil, & item_hit );
  449.         } while (( item_hit != kOKButtonID ) &&
  450.                  ( item_hit != kCancelButtonID ));
  451.  
  452.         if ( item_hit == kOKButtonID )
  453.         {    // we should really check to see if the password is different
  454.             // then save it only if it's not the same as the old password
  455.  
  456.             GetDItem( MyData.fconfig_dialog,
  457.                       kPasswordBoxID,
  458.                       & item_type,
  459.                       & item_handle,
  460.                       & item_box );
  461.             GetIText( item_handle, MyData.fold_password );
  462.             ARAWriteSecurityData( MyReference,
  463.                                   MyData.fold_password,
  464.                                   sizeof( MyData.fold_password ),
  465.                                   MyCompletionProc,
  466.                                   kStateStoredPassword );
  467.         }
  468.         else
  469.         {    // user selected cancel, just unlock the data
  470.             ARAUnlockSecurityData( MyReference,
  471.                                    MyCompletionProc,
  472.                                    kStateFinish );
  473.         }
  474.         DisposDialog( MyData.fconfig_dialog );
  475.     }
  476.  
  477.     return ( kSecurityNoErr );
  478. }
  479.  
  480.  
  481.  
  482. pascal void        MyCompletionProc( SecurityReference        MyReference,
  483.                                   int                    ResultCode,
  484.                                   void                    * DataPtr,
  485.                                   int                    DataSize,
  486.                                   long                    CompletionParam )
  487. //===========================================================================
  488. //    Description:    this is the completion routine that is called when
  489. //                    ARA Services have completed an asynchronous request.
  490. //                    We use the CompletionParam as a state indicator.  ARA
  491. //                    lets us know which state has just been completed so
  492. //                    we can make a transition to the appropriate next state.
  493. //                    When we call ARA services we provide the value for
  494. //                    CompletionParam (i.e. our state indicator).  This routine
  495. //                    is used for all asynchronous ARA routines.
  496. //
  497. //    Parameters:        MyReference            my unique identifier
  498. //                    ResultCode            result for the ARA call
  499. //                    DataPtr                pointer to the data we passed to ARA
  500. //                    DataSize            size of processed data (i.e. in the
  501. //                                        cases of reads or writes this may
  502. //                                        be different than what we passed to
  503. //                                        the ARA call)
  504. //                    CompletionParam        this is the parameter we passed to the
  505. //                                        ARA service.  We use it to indicate
  506. //                                        what state we are in.
  507. //
  508. //    Return Value:    none
  509. //
  510. //    Creation Date:    12/15/1992
  511. //
  512. //    Modifications:
  513. //
  514. //===========================================================================
  515. {    
  516.     if ( ResultCode == ARAAbort )            // we are being aborted
  517.                                             // don't do anything
  518.                                             // ARA services calls with this
  519.                                             // result code when we are
  520.                                             // aborting
  521.     {
  522.         return;
  523.     }
  524.  
  525.     switch ( CompletionParam )
  526.     {
  527.  
  528.         case    kStateGotPassword:            // got the existing password
  529.                                             // and the user name
  530.             // we need to put up the dialog box now.  But we can't do it
  531.             // here, because we may be called at interrupt time, so
  532.             // we send a tickle routine to ourselves.
  533.             if (( ResultCode != ARANoErr ) ||
  534.                 ( DataSize == 0 ))
  535.             {                                // initialize the password to
  536.                                             // the empty string
  537.                 ((char*) DataPtr )[ 0 ] = '\0';
  538.             }
  539.             ARATickleMe( MyReference, kStatePutUpDialog );
  540.             break;
  541.  
  542.  
  543.         case    kStateStoredPassword:        // wrote the new password out
  544.             // we have written a new password out.  We must now unlock the
  545.             // security configuration data
  546.  
  547.             if ( ARAUnlockSecurityData( MyReference,
  548.                                         MyCompletionProc,
  549.                                         kStateFinish ) != ARANoErr )
  550.             {
  551.                 ARACompleteOperation( MyReference );
  552.                 return;
  553.             }
  554.             break;
  555.  
  556.  
  557.         case    kStateFinish:                // all done
  558.             ARACompleteOperation( MyReference );
  559.             break;
  560.  
  561.  
  562.         case    kStateMiscCompletion:        // used for all the other completions
  563.         default:
  564.             break;                            // don't need to do anything, this is
  565.                                             // just used for routines for which we
  566.                                             // don't need to do anything.
  567.                                             // It is only put here to show this.
  568.     }
  569.  
  570.     return;
  571. }